Crackme 2002 par ReptileCrackeR [zip]
[Fichiers source du keygen]

Ce crackme est pas mal car il reprend la plupart des protections, donc pour se faire la main, c'est bien.

Ce programme est compressé avec PECompact, ben si vous me croyez pas, z'avez qu'à voir avec PEID ! Pis pour le décompresser, un p'tit outil bien sympa pour ceux qui veulent un peu de changement : UnPECompact. Il est consacré à ça, alors autant s'en servir ! Donc ouvrez le programme, sélectionnez le crackme, faîtes 'continuer', et vous avez un crackme tout propre ;op

Dans un autre tut, je montrerai comment patcher le programme sans l'unpacker avant, et également comment créer un loader correspondant.

NAGSCREEN :

C'est vraiment chiant ce message qui s'affiche à chaque lancement, vous trouvez pas ??? Allez, on lance IDA, on désassemble. Quand on lance le prog, le nag affiche "Ceci est une version blablabla". On peut toujours essayer de chercher le texte 'Ceci'. On lance la recherche, et on arrive ici :
.data:00401085
...mov esi, offset aCeciEstUneVers ; "Ceci est une version du crackme qui n'a"...

Si on descend, on aperçoit un 'call MessageBoxA' en 0040117F. On va alors poser un breakpoint à cette adresse sous OllyDbg (Ctrl+G, 0040117F et F2). On lance, ça breake. On peut voir dans la pile les messages de la MessageBox correspondant, et en effet en faisant F8 il s'agit bien de notre MessageBox. Eh bien on va faire en sorte qu'elle n'apparaisse plus.

Voici notre MessageBox avant :


0040116D |. 6A 00 .........PUSH 0 ....................; /Style = MB_OK|MB_APPLMODAL
0040116F |. 8D8D 20FFFFFF .LEA ECX,DWORD PTR SS:[EBP-E0] ....
......; |
00401175 |. 51 ............PUSH ECX ........................
.......; |Title
00401176 |. 8D95 30FFFFFF .LEA EDX,DWORD PTR SS:[EBP-D0] ....
......; |
0040117C |. 52 ............PUSH EDX ...............................; |Text
0040117D |. 6A 00 .........PUSH 0 .................................; |hOwner = NULL
0040117F |. FF15 B4524200 .CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA


La voici après :

0040116D |. 90 .............NOP
0040116E
|. 90 .............NOP
0040116F
|. 90 .............NOP
00401170
|. 90 .............NOP
00401171
|. 90 .............NOP
00401172
|. 90 .............NOP
00401173
|. 90 .............NOP
00401174
|. 90 .............NOP
00401175
|. 90 .............NOP
00401176
|. 90 .............NOP
00401177
|. 90 .............NOP
00401178
|. 90 .............NOP
00401179
|. 90 .............NOP
0040117A
|. 90 .............NOP
0040117B
|. 90 .............NOP
0040117C
|. 90 .............NOP
0040117D
|. 90 .............NOP
0040117E
|. 90 .............NOP
0040117F
|. 90 .............NOP
00401180
|. 90 .............NOP
00401181
|. 90 .............NOP
00401182
|. 90 .............NOP
00401183
|. 90 .............NOP
00401184
|. 90 .............NOP

Alors c'est pas mieux là ?
On a tout simplement remplacé l'appel de la MessageBox par rien. L'instruction NOP permet de passer à l'instruction suivante, en faisant ceci pour tous les push et le call le NAG est détruit ! On prend notre éditeur hexa, on ouvre le fichier exécutable, on cherche 6A008D8D20FFFFFF, et on remplace cette chaîne et celles qui suivent par 24 90 (24 NOP, pas 2490 le chiffre, argh...), car 90 c'est NOP en hexadécimal.

Bref vous changez
6A 008D 8D20 FFFF FF51 8D95 30FF FFFF 526A 00FF 15B4 5242 00
par
90 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 9090 90
vous sauvegardez et voilà un programme sans nag ;op

Cependant ceci n'est pas très propre, car c'est beaucoup de code pour rien, on exécute 23 lignes alors qu'on pourrait en exécuter qu'une : nous allons directement sauter par dessus le MessageBox. On se place donc en 0040116D, on double clique sur le code assembleur, et on veut détourner le code vers l'adresse 401185, on modifie donc le code par JMP 00401185. On obtient donc maintenant :

0040116B |. 8BF4 ..............MOV ESI,ESP
0040116D
|. EB 16 .............
JMP SHORT _unpacke.00401185
0040116F |. 8D8D 20FFFFFF .....LEA ECX,DWORD PTR SS:[EBP-E0] ............; |
00401175 |. 51 ................PUSH ECX .................................; |Title
00401176 |. 8D95 30FFFFFF .....LEA EDX,DWORD PTR SS:[EBP-D0] ............; |
0040117C |. 52 ................PUSH EDX .................................; |Text
0040117D |. 6A 00 .............PUSH 0 ...................................; |hOwner = NULL
0040117F |. FF15 B4524200 .....CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
00401185 |. 3BF4 ..............CMP ESI,ESP

En effet le jump passera donc par dessus l'appel du nag-screen, et le code pourra ainsi continuer. On remplace donc 6A00 par EB16. Pensez à regardez les octets avant et après pour vérifier que vous modifier le bon 6A00, ce serait dommage d'en modifier un autre et de faire planter le crackme, et de ne pas avoir résolu le problème.

NOM/PRENOM/NUMERO DE SERIE :
On va donc rechercher le message d'erreur qui s'affiche. On a beau désassembler le fichier exe avec IDA et chercher le texte, on ne trouve pas. Désassemblons la DLL, on trouvera sûrement quelque chose de plus intéressant. Et on tombe sur ceci :

CODE:0045501E...loc_45501E: ; CODE XREF: sub_454E28+1E8|j
CODE:0045501E.. mov eax, offset aNumsroDeSsrieR ; "NumÚro de sÚrie refusÚ !"
CODE:00455023
..call sub_42D6F0


On double-clique sur l'adresse en vert et on arrive en 00455010 (0x454E28+0x1E8).


CODE:0045500C loc_45500C: ; CODE XREF: sub_454E28+1DD|j
CODE:0045500C cmp [ebp+var_8], 1
CODE:00455010 jnz short loc_45501E
CODE:00455012 mov eax, offset aNumsroDeSsrieA ; "NumÚro de sÚrie acceptÚ !"
CODE:00455017 call sub_42D6F0
CODE:0045501C jmp short loc_455028
CODE:0045501E ; -------------------------------------------------------------------
CODE:0045501E
CODE:0045501E loc_45501E: ; CODE XREF: sub_454E28+1E8|j
CODE:0045501E mov eax, offset aNumsroDeSsrieR ; "NumÚro de sÚrie refusÚ !"
CODE:00455023 call sub_42D6F0


Si on remonte, on s'aperçoit que la procédure commence en 00454E28. On va donc poser un breakpoint à cette adresse. Mais si nous essayons de le poser comme d'habitude, ce n'est pas possible, car le programme est lancé à partir de la DLL, et tourne comme processus, c'est-à-dire qu'il est exécuté à partir d'un autre programme, ici le fichier crackme.exe.

On va donc d'abord exécuter le crackme, et ensuite dans OllyDbg, au lieu de faire 'Open', on fait 'Attach', et on sélectionne le crackme. Ensuite on peut poser le breakpoint en 454E28. En faisant du pas à pas avec F8, le programme concatène la chaîne du nom avec la chaîne "n-gen", et ensuite le prénom ce qui donne par exemple : Le_MaLaDen-genShmeitCorp.
Ensuite vient les routines de génération du numéro de série :

00454E84 BB FF000000
..........MOV EBX,0FF
00454E89 8B45 F4
..............MOV EAX,DWORD PTR SS:[EBP-C]
00454E8C E8 DFF8FAFF
..........CALL crackme.00404770
00454E91 8BC8
.................MOV ECX,EAX
00454E93 85C9
.................TEST ECX,ECX
00454E95 7E 25
................JLE SHORT crackme.00454EBC
00454E97 BA 01000000
..........MOV EDX,1
00454E9C 8B45 F4
..............MOV EAX,DWORD PTR SS:[EBP-C]
00454E9F 0FB64410 FF
..........MOVZX EAX,BYTE PTR DS:[EAX+EDX-1]
00454EA4 69C0 B3150000
........IMUL EAX,EAX,15B3
00454EAA 03D8
.................ADD EBX,EAX
00454EAC 69C2 B3150000
........IMUL EAX,EDX,15B3
00454EB2 03D8
.................ADD EBX,EAX
00454EB4 8BC3
.................MOV EAX,EBX
00454EB6 8BD8
.................MOV EBX,EAX
00454EB8 42
...................INC EDX
00454EB9 49
...................DEC ECX
00454EBA 75 E0
................JNZ SHORT crackme.00454E9C

On multiplie la valeur ASCII d'un caractère par 5555 (0x15B3), qu'on additionne à EBX initialisé à 255 (0xFF).
On multiplie la position du caractère sélectionné par 5555 également, qu'on additionne à EBX.
On recommence pour chaque caractère. On effectue 2 autres fois cette routine, mais en multipliant par 2222, puis par 8888 et en reprenant la valeur d'EBX de la routine précédente à chaque fois. On vérifie ensuite le numéro ainsi généré avec celui saisi.
Vient ensuite une autre routine qui multiplie cette fois par 4444, mais c'est une feinte ;op Elle ne sert à rien.
Le crackme compare ensuite le numéro ainsi généré avec celui entré. Vous pouvez retrouver l'algo utilisé pour le keygen dans la source fournie.

KEYFILE :
Ici pour trouver la routine, on peut procéder de la même manière, ou tout simplement dans IDA voir qu'au-dessus de la routine du keygen se trouve la routine de la base de registres, et au-dessus la routine du keyfile en 004550F0.
On breakpointe (du verbe breakpointer, prenez tous votre Bescherelle) donc en 4550F0. Alors le programme cherche donc un fichier :

00455124 BA 6C524500 MOV EDX,crackme.0045526C ; ASCII "n-gen.key"

Ensuite en 00455180 on lit le contenu du fichier. Puis on divise avec l'instruction 'SAR EDI, 1' par 2 le nombre de caractères lus.
On fait la même chose avec ESI. Je passe quelques lignes qui ne nécessitent pas d'être commentées. Nous voilà ensuite à la routine de vérification du keyfile.

004551A3 BB 01000000...........MOV EBX,1
004551A8 47 ...................INC EDI
004551A9 8B45 FC ..............MOV EAX,DWORD PTR SS:[EBP-4] .....; On charge le
.................................................................; contenu du file
004551AC 0FB64418 FF ..........MOVZX EAX,BYTE PTR DS:[EAX+EBX-1] ; On prend un
.................................................................; caractère
004551B1 8D145B ...............LEA EDX,DWORD PTR DS:[EBX+EBX*2] .; Petite opération
.................................................................; EDX = 3*EBX
004551B4 03C2 .................ADD EAX,EDX ......................; On additionne
.................................................................; EDX au code .................................................................;.ASCII du .................................................................; caractère
004551B6 8B55 FC ..............MOV EDX,DWORD PTR SS:[EBP-4]
004551B9 0FB6543A FF ..........MOVZX EDX,BYTE PTR DS:[EDX+EDI-1] ; On extrait le
.................................................................; caractère à la
.................................................................; même position .................................................................; dans la 2ème .................................................................; moitié
004551BE 3BC2 .................CMP EAX,EDX ......................; On compare ce
............ ............ ............ ............ ............ ;.car. au car. à ............ ............ ............ ............ ............ ;.la position EDX
004551C0 75 0D ................JNZ SHORT crackme.004551CF
004551C2 8D45 FC ..............LEA EAX,DWORD PTR SS:[EBP-4]
004551C5 8B55 FC ..............MOV EDX,DWORD PTR SS:[EBP-4]
004551C8 E8 83F3FAFF ..........CALL crackme.00404550
004551CD EB 07 ................JMP SHORT crackme.004551D6
004551CF C745 F4 01000000 .....MOV DWORD PTR SS:[EBP-C],1
004551D6 8D85 24FEFFFF ........LEA EAX,DWORD PTR SS:[EBP-1DC]
004551DC 8B55 FC ..............MOV EDX,DWORD PTR SS:[EBP-4]
004551DF 8A541A FF ............MOV DL,BYTE PTR DS:[EDX+EBX-1]
004551E3 E8 B0F4FAFF ..........CALL crackme.00404698
004551E8 8B95 24FEFFFF ........MOV EDX,DWORD PTR SS:[EBP-1DC]
004551EE 8D45 F8 ..............LEA EAX,DWORD PTR SS:[EBP-8]
004551F1 E8 82F5FAFF ..........CALL crackme.00404778
004551F6 43 ...................INC EBX
004551F7 4E ...................DEC ESI
004551F8 75 AE ................JNZ SHORT crackme.004551A8


Donc tout simplement on ne parcourt que la première moitié du fichier qui correspond en fait au nom, on multiplie sa position par 3 qu'on additionne au code ASCII du caractère qui sera en fait le caractère dans la 2ème moitié du keyfile;

Exemple : L e _ M a l a d e
Position : 1 2 3 4 5 6 7 8 9
Position*3 : 3 6 9 12 15 18 21 24 27
Code ASCII : 4C 65 5F 4D 61 4C 61 44 65
                   
Somme : 4F 6B 68 59 70 5E 76 5C 80

Pour moi donc le keyfile aura cette forme avec un éditeur hexa :
4C65 5F4D 614C 6144 654F 6B68 5970 5E76 5C80
Voilà, c'est tout simple.

REGISTRE WINDOWS :
Bon, dernière partie, ça va aller vite aussi car c'est toujours le même principe...
Dans IDA on a repéré que la routine débutait en 004552B8. Vous savez ce qu'il vous reste à faire.
On voit très clairement dans IDA en 00455310 que la clé sera en '\Software\Microsoft\Windows\RegCrkme'. Mais il nous manque la première clé.

En 004552F0 on voit une valeur hexa... c'est peut-être ce qu'on cherche.
Un clic-droit sur la valeur, 'Use standard symbolic constant' et on voit HKEY_LOCAL_MACHINE ;o)

CODE:004552F0 mov edx, HKEY_LOCAL_MACHINE
CODE:004552F5 mov eax, [ebp+var_10]
CODE:004552F8 call sub_454734
CODE:004552FD mov edx, offset dword_45543C
CODE:00455302 mov eax, [ebp+var_10]
CODE:00455305 call sub_454AB8
CODE:0045530A test al, al
CODE:0045530C jz short loc_455341
CODE:0045530E mov cl, 1
CODE:00455310 mov edx, offset aSoftwareMicros ; "\\Software\\Microsoft\\Windows\\RegCrkme"
CODE:00455315 mov eax, [ebp+var_10]
CODE:00455318 call sub_454798sub_454798

Alors le programme cherche 2 valeurs dans cette clé : 'key' et 'nom'. On prend ensuite la valeur se trouvant dans le champ 'nom', et on boucle :

00455363 E8 08F4FAFF .....CALL crackme.00404770
00455368 8BD8
............MOV EBX,EAX ; EBX = nombre de caractères du nom
0045536A 85DB
............TEST EBX,EBX
0045536C 7E 20
...........JLE SHORT crackme.0045538E
0045536E B8 01000000
.....MOV EAX,1
00455373 8B55 F8
.........MOV EDX,DWORD PTR SS:[EBP-8] .....; on charge le nom
00455376 0FB65402 FF
.....MOVZX EDX,BYTE PTR DS:[EDX+EAX-1] ; on prend une lettre
0045537B 69D2 050D0000
...IMUL EDX,EDX,0D05 ................; qu'on multiplie par ...................... ........... ........... .............;.3333 (0x0D05)
00455381 0355 F4
.........ADD EDX,DWORD PTR SS:[EBP-C]  ... ; on additionne la ...................... ........... ........... ........... .;.valeur stockée ...................... ........... ........... ........... .;.(initialement à 0)
00455384 83C2 0A
.........ADD EDX,0A ......... .............; on ajoute 10
00455387 8955 F4
.........MOV DWORD PTR SS:[EBP-C],EDX .....; on la stocke
0045538A 40
..............INC EAX ......... ............... ; on passe au caractère ...................... ........... ........... ........... .;.suivant
0045538B 4B
..............DEC EBX
0045538C 75 E5
...........JNZ SHORT crackme.00455373

Ensuite on vérifie le numéro avec celui se trouvant dans le champs 'key'. On place la valeur de EDX dans ce champs 'key', on appuie sur le bouton, et le programme est enregistré à partir du registre.

CONCLUSION :

Alors le nag est viré, on a créé un keygen, on a notre keyfile, ensuite on a créé les clés nécessaires dans le registre Windows... bon le crackme est fini ! Ouf ! Car ça commençait à devenir long d'expliquer, lol. Donc vous avez vu que le principe est presque toujours le même, une fois qu'on a la main avec ce genre de crackme, ça se fait très vite. Je vous fournis un source pour ce crackme, n'hésitez pas à y jeter un oeil et à poser vos questions. Maintenant je vais aller dormir car ce tutz je l'ai pas fait en un jour...

Allez, la prochaine fois j'essaierais de faire quelque chose de plus dur. Ah, et j'espère que cette série de tutz vous a permi de découvrir de nouveaux outils, vous aurez remarqué que je n'ai utilisé ni Soft-Ice, ni Win32Dasm.